home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Documentation / DirectX9 / directx9_m.chm / directx / code / xslutil.js < prev   
Encoding:
Text File  |  2004-09-30  |  39.7 KB  |  1,500 lines

  1. <![CDATA[
  2.  
  3.   //var MyObj = new object();
  4.   
  5.   // simple context object that caches project-specific settings defined in settings.dtd
  6.   function CContext(oDoc, sDevLang, sMedia, sDelivery, sDomain, sExt, sProj, sProjMask, sDefPlat, iAllowSelfUnregistered, iLuCache, iUseTargetsV2) //at //markda
  7.   {
  8.     this._oDoc = oDoc; // cache a reference to the current XML document
  9.     this._devlang = sDevLang;
  10.     this._media = sMedia;
  11.     this._delivery = sDelivery;
  12.     this._domain = sDomain;
  13.     this._ext = sExt;
  14.     this._proj = sProj
  15.     this._projMask = sProjMask;
  16.     this._defPlat = sDefPlat;
  17.     this._bAllowSelfUnregistered = (iAllowSelfUnregistered ? true : false);
  18.     this._paths = new Array();
  19.  
  20.     //markda: Switch that determines if targets v1 or v2 is used
  21.     this._bUseTargetsV2 = (iUseTargetsV2 ? true : false);
  22.  
  23.     //at: Switch that determines if lookup caching is done (ie, LuCache).
  24.     this._bCacheLookups = (iLuCache ? true : false);
  25.  
  26.     //at: Following code creates the target node "mini-dom" and
  27.     //at: gets local hard drive for later targets.xml path assembly.
  28.     this._oTDom = new ActiveXObject("Microsoft.XMLDOM");
  29.     var re = /\/\/.:/i;
  30.     var n = oDoc.url.search(re);
  31.     if (n > 0)
  32.     {
  33.       var sVal = oDoc.url.substr(n+2, 2);
  34.       this._sDrive = sVal.toLowerCase();
  35.     }
  36.     else
  37.       this._sDrive = "";
  38.   }
  39.  
  40.   CContext.prototype.GetPathOf = function(sKey)
  41.   {
  42.     return this._paths[sKey];
  43.   }
  44.  
  45.   CContext.prototype.SetPathOf = function(sKey, sPath)
  46.   {
  47.     this._paths[sKey] = sPath;
  48.   }
  49.  
  50.   // return a reference to the current document
  51.   CContext.prototype.GetDocument = function()
  52.   {
  53.     return this._oDoc;
  54.   }
  55.  
  56.   CContext.prototype.GetDevLang = function()
  57.   {
  58.     return this._devlang;
  59.   }
  60.  
  61.   CContext.prototype.GetDefaultPlatform = function()
  62.   {
  63.     return this._defPlat;
  64.   }
  65.  
  66.   CContext.prototype.AllowSelfUnregistered = function()
  67.   {
  68.     return this._bAllowSelfUnregistered;
  69.   }
  70.  
  71.   //at: Return true if Lookup Caching is on.
  72.   CContext.prototype.CacheLookups = function()
  73.   {
  74.     return this._bCacheLookups;
  75.   }
  76.  
  77.   //at: Force Turn off of lookup caching.
  78.   CContext.prototype.NoCacheLookups = function()
  79.   {
  80.     this._bCacheLookups = false;
  81.   }
  82.  
  83.   //markda: Return true if targets v2 required
  84.   CContext.prototype.UseTargetsV2 = function()
  85.   {
  86.     return this._bUseTargetsV2;
  87.   }
  88.  
  89.   // if an iface is marked as primary, return it
  90.   // if more than one iface is marked as primary, return the first
  91.   // if no ifaces are marked as primary, return the first
  92.   function GetActiveIFace()
  93.   {
  94.     var oActiveIFaces = ownerDocument.selectNodes("/inetsdk:topic/metadata/applies/iface[@primary]");
  95.     if (oActiveIFaces.length == 0)
  96.     {
  97.       var oActiveIFace = ownerDocument.selectSingleNode("/inetsdk:topic/metadata/applies/iface[0]");
  98.       return oActiveIFace;
  99.     }
  100.     else
  101.     {
  102.       return oActiveIFaces[0];
  103.     }
  104.   }
  105.  
  106.   // does the current topic contain at least one remark specific to the specified platform
  107.   function ContainsQualifyingRemarkForPlatform(oContainer, sDesiredPlat, sCurDLang)
  108.   {
  109.     var sDLangClause = "";
  110.     if (sCurDLang != '')
  111.     {
  112.       sDLangClause = " $and$ not(@devlang) $or$ @devlang='" + sCurDLang + "'";
  113.     }
  114.  
  115.     // ASSumes the current context is the parent of remarks
  116.     var oPotentialRems = oContainer.selectNodes("remarks/rem[@platforms" + sDLangClause + "]");
  117.     if (!oPotentialRems)
  118.     {
  119.       return false;
  120.     }
  121.  
  122.     var oRegDesiredPlat = new RegExp("\\b" + sDesiredPlat + "\\b");
  123.     for (var i = 0; i < oPotentialRems.length; i++)
  124.     {
  125.       // check to see if there's a rem specific to the specified platform
  126.       if (IsQualifyingRemarkForPlatform(oPotentialRems[i], sDesiredPlat, oRegDesiredPlat, true)  && IsQualifyingRemarkForActiveIFace(oPotentialRems[i], sCurDLang))
  127.       {
  128.         return true;
  129.       }
  130.     }
  131.  
  132.     return false;
  133.   }
  134.  
  135.   // Return true if the specified remark applies to the desired platform
  136.   // oRegDesiredPlat can be passed in as an optimization
  137.   // When set to true, bFailIfNone indicates that the rem shouldn't qualify if no platforms are specified
  138.   function IsQualifyingRemarkForPlatform(oRem, sDesiredPlat, oRegDesiredPlat, bFailIfNone)
  139.   {
  140.     var sPlatforms = oRem.getAttribute("platforms");
  141.  
  142.     if (!bFailIfNone)
  143.     {
  144.       bFailIfNone = false;
  145.     }
  146.  
  147.     // no platforms were specified
  148.     if (!sPlatforms)
  149.     {
  150.       return (bFailIfNone ? false : true);
  151.     }
  152.  
  153.     if (!oRegDesiredPlat)
  154.     {
  155.       oRegDesiredPlat = new RegExp("\\b" + sDesiredPlat + "\\b");
  156.     }
  157.  
  158.     if (oRegDesiredPlat.test(sPlatforms))
  159.     {
  160.       return true;
  161.     }
  162.  
  163.     return false;
  164.   }
  165.  
  166.   // does the topic contain any remarks that qualify
  167.   // in the script case is there a remark that's either lang-neutral or script specific
  168.   // in the cpp case is there a remark that's either lang-neutral or cpp specific. If it's cpp specific, does it pertain to the active iface
  169.   // in the vb case?
  170.   function ContainsQualifyingRemarkForDefaultPlatform(oCtx)
  171.   {
  172.     var oDoc = oCtx.GetDocument();
  173.     if (!oDoc)
  174.     {
  175.       return false;
  176.     }
  177.  
  178.     var sBaseQ = "/inetsdk:topic/content/remarks";
  179.     var sCurLang = oCtx.GetDevLang();
  180.     var sDefPlat = oCtx.GetDefaultPlatform();
  181.  
  182.     // is there a rem or a note that's devlang neutral?
  183.     var oRems = oDoc.selectNodes(sBaseQ + "/rem[not(@devlang)] | " + sBaseQ + "/note[not(@devlang)]");
  184.     if ((0 == oRems.length) && (!sCurLang || (/^\s*$/.test(sCurLang))))
  185.     {
  186.       // this is a language neutral topic that doesn't contain any neutral remarks. bail!
  187.       return false;
  188.     }
  189.  
  190.     // do one of the devlang neutral remarks qualify for the default platform?
  191.     for (var iRem = 0; iRem < oRems.length; iRem++)
  192.     {
  193.       var oRem = oRems(iRem);
  194.       // 110440: be sure to check for iface filter (@rids) since a remark can apply to any language but be restricted to
  195.       // a particular iface in the cpp case
  196.       if (IsQualifyingRemarkForPlatform(oRem, sDefPlat) && IsQualifyingRemarkForActiveIFace(oRem, sCurLang))
  197.       {
  198.         return true;
  199.       }
  200.     }
  201.  
  202.     // now deal with devlang-specific remarks
  203.     oRems = oDoc.selectNodes(sBaseQ + "/rem[@devlang='" + sCurLang + "'] | " + sBaseQ + "/note[@devlang='" + sCurLang + "']");
  204.     if (oRems.length == 0)
  205.     {
  206.       return false;
  207.     }
  208.  
  209.     // drill in to see if the rem applies to the active iface
  210.     for (iRem = 0; iRem < oRems.length; iRem++)
  211.     {
  212.       var oRem = oRems(iRem);
  213.       if (IsQualifyingRemarkForPlatform(oRem, sDefPlat) && IsQualifyingRemarkForActiveIFace(oRem, sCurLang))
  214.       {
  215.         return true;
  216.       }
  217.     }
  218.  
  219.     return false;
  220.   }
  221.  
  222.   // should the remark be included or filtered out
  223.   function IsQualifyingRemarkForActiveIFace(oRem, sCurLang)
  224.   {
  225.     var sRIDs = oRem.getAttribute("rids");
  226.     if (!sRIDs)
  227.     {
  228.       return true;
  229.     }
  230.  
  231.     if ('cpp' != sCurLang)
  232.     {
  233.       return true;
  234.     }
  235.  
  236.     var oActiveIFace = GetActiveIFace();
  237.     if (!oActiveIFace)
  238.     {
  239.       return true;
  240.     }
  241.  
  242.     var sActiveRID = oActiveIFace.getAttribute("rid");
  243.     if (!sActiveRID)
  244.     {
  245.       // Yikes! DTD should NEVER allow this to occur
  246.       return true;
  247.     }
  248.  
  249.     var oRegInList = new RegExp("\\b" + sActiveRID + "\\b");
  250.  
  251.     if (oRegInList.test(sRIDs))
  252.     {
  253.       return true;
  254.     }
  255.  
  256.     return false;
  257.  
  258.   }
  259.  
  260.   // added by chains 09/29/2000 (petertay)
  261.   // does the topic contain any params that qualify for active iface
  262.   function ContainsQualifyingParamForActiveIface(oCtx)
  263.   {
  264.  
  265.     var oDoc = oCtx.GetDocument();
  266.     if (!oDoc)
  267.     {
  268.       return false;
  269.     }
  270.  
  271.     var sBaseQ = "/inetsdk:topic/content/params";
  272.     var sCurLang = oCtx.GetDevLang();
  273.  
  274.     // is there a param that's devlang neutral?
  275.     var oParamColl = oDoc.selectNodes(sBaseQ + "/param");
  276.  
  277.     // do one of the devlang neutral remarks qualify for the active iface?
  278.     for (var iParam = 0; iParam < oParamColl.length; iParam++)
  279.     {
  280.       var oParam = oParamColl(iParam);
  281.  
  282.     // Filter out params w/autodesc and no script desc
  283.     // autodesc not currently supported in script
  284.     if (oParam.getAttribute("autodesc") && sCurLang == "scr")
  285.     {
  286.       var oScrDesc = oParam.selectNodes("desc[@devlang='scr']");
  287.     if (oScrDesc.length == 0) continue;
  288.     }
  289.       if (QualifiesForActiveIFace(oParam, sCurLang))
  290.       {
  291.         return true;
  292.       }
  293.     }
  294.  
  295.     // now deal with devlang-specific remarks
  296.     oParamColl = oDoc.selectNodes(sBaseQ + "/param[@devlang='" + sCurLang + "']");
  297.     if (oParamColl.length == 0)
  298.     {
  299.       return false;
  300.     }
  301.  
  302.     // drill in to see if the param applies to the active iface
  303.     for (iParam = 0; iParam < oParamColl.length; iParam++)
  304.     {
  305.       var oParam = oParamColl(iParam);
  306.       if (QualifiesForActiveIFace(oParam, sCurLang))
  307.       {
  308.         return true;
  309.       }
  310.     }
  311.  
  312.     return false;
  313.   }
  314.  
  315.   // added by chains 09/29/2000 (petertay)
  316.   // should the param be included or filtered out
  317.   function QualifiesForActiveIFace(oElem, sCurLang)
  318.   {
  319.     var sRIDs = oElem.getAttribute("rids");
  320.     if (!sRIDs)
  321.     {
  322.       return true;
  323.     }
  324.  
  325.     if (sCurLang != 'cpp')
  326.     {
  327.       return true;
  328.     }
  329.  
  330.     var oActiveIFace = GetActiveIFace();
  331.     if (!oActiveIFace)
  332.     {
  333.       return true;
  334.     }
  335.  
  336.     var sActiveRID = oActiveIFace.getAttribute("rid");
  337.     if (!sActiveRID)
  338.     {
  339.       // Yikes! DTD should NEVER allow this to occur
  340.       return true;
  341.     }
  342.  
  343.     var oRegInList = new RegExp("\\b" + sActiveRID + "\\b");
  344.  
  345.     if (oRegInList.test(sRIDs))
  346.     {
  347.       return true;
  348.     }
  349.  
  350.     return false;
  351.  
  352.   }
  353.  
  354.  
  355.   // If the type start with a vowel or an H, the data type is soft
  356.   // sounds and should be preceded by "an" rather than "a".
  357.   function IsSoftSounding(sType)
  358.   {
  359.     if (!sType)
  360.     {
  361.       return false;
  362.     }
  363.     var oReg = /^[AaEeIiOoUuH]/;
  364.     return (oReg.test(sType) ? true : false);
  365.   }
  366.  
  367.   // This is only a poor guess that the param represented by o describes an interface
  368.   function IsIFace(o)
  369.   {
  370.     var sType = o.getAttribute('type');
  371.     if (!sType)
  372.     {
  373.       return false;
  374.     }
  375.  
  376.     if (sType.substring(0,1) == "I" && o.getAttribute('pointerlevel') >= 1)
  377.     {
  378.       return true;
  379.     }
  380.     else
  381.     {
  382.       return false;
  383.     }
  384.   }
  385.  
  386.   // Return a portion of the path using the specified mask
  387.   // iPortion values:
  388.   //  0 == text before the mask,
  389.   //  1 == text following the mask,
  390.   //  2 == text before and including the mask,
  391.   //  3 == text after and including the mask
  392.   // if the mask cannot be found within the path, the entire path is returned
  393.   function PartialPathOf(sPath, sMask, iPortion)
  394.   {
  395.     if (typeof(iPortion) == 'undefined')
  396.     {
  397.       return sPath;
  398.     }
  399.   //normalize the path. The document path when loaded from IE uses "/". But when loaded from script it uses "\".
  400.   while (sPath.indexOf("\\")!=-1)
  401.   {
  402.     sPath=sPath.replace("\\","/");
  403.   }
  404.  
  405.     var oReg = new RegExp("(.*)" + sMask + "(.*)", "i");
  406.     if (oReg.test(sPath))
  407.     {
  408.       switch(iPortion)
  409.       {
  410.       case 0:
  411.         return RegExp.$1;
  412.       case 1:
  413.         return RegExp.$2;
  414.       case 2:
  415.         return RegExp.$1 + sMask;
  416.       case 3:
  417.         return sMask + RegExp.$2;
  418.       }
  419.     }
  420.     else
  421.     {
  422.       return sPath;
  423.     }
  424.   }
  425.  
  426.   // replicate the specified string (sRepl) iTimes times.
  427.   function ReplStr(sRepl, iTimes)
  428.   {
  429.     var sOut = "";
  430.     for (var i = 0; i < iTimes; i++)
  431.     {
  432.       sOut+=sRepl;
  433.     }
  434.     return sOut;
  435.   }
  436.  
  437.   // Given an associative array, convert it to a string where each item is separated by the specified delimeter
  438.   function StringFromHash(aHash, sDelim)
  439.   {
  440.     var s = "";
  441.     for (sItem in aHash)
  442.     {
  443.       s += sItem + sDelim;
  444.     }
  445.  
  446.     var oReg = new RegExp(sDelim + "$");
  447.     s = s.replace(oReg, ""); // lop off trailing comma
  448.     return s;
  449.   }
  450.  
  451.   // Collect the conceptual index entries from the doc.
  452.   // Indexer expects to find these as an IDX_CONCEPT expando on the top-level H1.
  453.   // Web Crawlers expect to find these in the Keywords META.
  454.   // HTMLHelp expects to find these in MS-HKWD METAs.
  455.   function GatherConcepts(o, sDelim)
  456.   {
  457.     var aConcepts = {};
  458.     var oDoc = o.ownerDocument;
  459.  
  460.     var sIndexQuery = "/inetsdk:topic/metadata/index";
  461.     var oIndex = oDoc.selectSingleNode(sIndexQuery);
  462.     var bNoDefIndex = false;
  463.     if (oIndex)
  464.     {
  465.       if (oIndex.getAttribute("noindex"))
  466.       {
  467.         bNoDefIndex = true;
  468.       }
  469.  
  470.       var oKeyWords = oIndex.selectNodes("kw");
  471.       for (var iKW = 0; iKW < oKeyWords.length; iKW++)
  472.       {
  473.         aConcepts[oKeyWords[iKW].text.toLowerCase()] = "1";
  474.       }
  475.     }
  476.  
  477.     // delimeter specification indicates that the output is for IDX_CONCEPT
  478.     // since indexer will index the topic name, don't repeat it in the concept list
  479.     if (!bNoDefIndex && !sDelim)
  480.     {
  481.       var sNameQuery = "/inetsdk:topic/metadata/@name";
  482.       var oName = oDoc.selectSingleNode(sNameQuery);
  483.       if (oName)
  484.       {
  485.         aConcepts[oName.value] = "1";
  486.       }
  487.     }
  488.  
  489.     if (sDelim)
  490.     {
  491.       return StringFromHash(aConcepts, sDelim);
  492.     }
  493.     else
  494.     {
  495.       return aConcepts;
  496.     }
  497.   }
  498.  
  499.   // Collect keywords from the document and spit them out as <META KEYWORDS.../>
  500.   // This code recognizes <kw> tags and <tla> and <term> tags with a kw attribute
  501.   // Consider supporting <xref> with a kw attribute.
  502.   // avoid dupes by converting all keywords to lowercase and by storing them in a hash table
  503.   function GatherKeywords(o, sDelim)
  504.   {
  505.     var oDoc = o.ownerDocument;
  506.  
  507.     if (!sDelim)
  508.     {
  509.       sDelim = ",";
  510.     }
  511.  
  512.     // don't pass a delimeter because we want to get back a hash table
  513.     var aKeywords = GatherConcepts(o);
  514.  
  515.     var sQuery = "/inetsdk:topic/content//kw";
  516.     var oNodes = oDoc.selectNodes(sQuery);
  517.     var i;
  518.     for (i = 0; i < oNodes.length; i++)
  519.     {
  520.       var oNode = oNodes[i];
  521.       aKeywords[oNode.text.toLowerCase()] = "1";
  522.     }
  523.  
  524.     sQuery = "/inetsdk:topic/content//tla[@kw]";
  525.     oNodes = oDoc.selectNodes(sQuery);
  526.     for (i = 0; i < oNodes.length; i++)
  527.     {
  528.       //at: Search the central pre-loaded acronyms.xml DOM.
  529.       var sRid = oNodes[i].getAttribute("rid");
  530.       var oAc = goLookup.RetrieveAcronym(sRid);
  531.       if (oAc)
  532.       {
  533.         var oNode = oAc.selectSingleNode("primary");
  534.         if (oNode)
  535.           aKeywords[oNode.text.toLowerCase()] = "1";
  536.       }
  537.     }
  538.  
  539.     sQuery = "/inetsdk:topic/content//term[@kw]";
  540.     oNodes = oDoc.selectNodes(sQuery);
  541.     for (i = 0; i < oNodes.length; i++)
  542.     {
  543.       var oNode = oDoc.selectSingleNode("/inetsdk:topic/inetsdk:glossary/gloss_entry[@id = '" + oNodes[i].getAttribute("rid") + "']/@name");
  544.       if (oNode)
  545.       {
  546.         aKeywords[oNode.text.toLowerCase()] = "1";
  547.       }
  548.     }
  549.  
  550.     return StringFromHash(aKeywords, sDelim);
  551.   }
  552.  
  553.   var gSpecialContainer = {"seealso" : 1, "applies" : 1, "related_topics" : 1};
  554.   function IsPrivilegedLink(o)
  555.   {
  556.     //return (gSpecialContainer[o.parentNode.nodeName] != null ? true : false);
  557.  
  558.     // need to walk the parent chain since links can be embedded inside if/sw and other markup
  559.     // rather than directly inside a special container
  560.     var oParent = o;
  561.     while (oParent = oParent.parentNode)
  562.     {
  563.       if (gSpecialContainer[oParent.nodeName] != null)
  564.       {
  565.         return true;
  566.       }
  567.     }
  568.     return false;
  569.   }
  570.  
  571.   // determine whether or not this link should be enabled
  572.   // rule: must be the first instance or must be explicitly enabled
  573.   function ShouldLink(oSrc, oCtx)
  574.   {
  575.     return (oSrc.getAttribute("enabled") || IsPrivilegedLink(oSrc) || IsFirstLink(oSrc, oCtx) ? true : false);
  576.   }
  577.  
  578.   // determine whether or not the node should be glossarized
  579.   // rule: must be the first instance or must be explicitly enabled
  580.  
  581.   // keep tabs on glossary references. This is a more memory intensive but
  582.   // less processing intensive (fewer DOM query/traverses), and more
  583.   // reliable since a gloss entry may be referenced earlier in the tree but for a
  584.   // different dev language
  585.  
  586.   function ShouldGlossarize(o)
  587.   {
  588.     var sID = o.getAttribute("rid");
  589.     if (!sID) return false;
  590.  
  591.     if (typeof(ShouldGlossarize._table) == 'undefined')
  592.     {
  593.       ShouldGlossarize._table = new Array();
  594.       ShouldGlossarize._table[sID] = 1;
  595.       return true;
  596.     }
  597.  
  598.     if (!ShouldGlossarize._table[sID])
  599.     {
  600.       ShouldGlossarize._table[sID] = 1;
  601.       return true;
  602.     }
  603.  
  604.     if (o.getAttribute("enabled"))
  605.     {
  606.       return true;
  607.     }
  608.  
  609.     return false;
  610.   }
  611.  
  612.  
  613.   // determine if the link (o) is the first occurrence of a
  614.   // cross-reference to the topic with the specified @rid
  615.   // BUGBUG: Check for type="pn", and concatenate that onto the key
  616.   function IsFirstLink(o, oCtx)
  617.   {
  618.     var sID = o.getAttribute("rid");
  619.     if (!sID) sID = o.getAttribute("ALINK"); // For auxguts.xsl
  620.     if (!sID) return false;
  621.  
  622.     var sFid = o.getAttribute("fid"); // #fragment-id
  623.     var sIid = o.getAttribute("iid"); // #interface-id
  624.     var sCid = o.getAttribute("cid"); // #constant-id
  625.  
  626.     // use the devlang on the source tag before the global devlang
  627.     var sDevLang = o.getAttribute("devlang");
  628.     if (!sDevLang)
  629.     {
  630.       sDevLang = oCtx._devlang;
  631.     }
  632.  
  633.     // differentiate between persistent and runtime requests
  634.     var sType = o.getAttribute("type");
  635.  
  636.     var sKey = sID +
  637.       (typeof(sDevLang) != 'undefined' ? sDevLang : '') +
  638.       (sFid != null ? sFid : '') +
  639.       (sIid != null ? sIid : '') +
  640.       (sCid != null ? sCid : '') +
  641.       (sType != null ? sType : '');
  642.  
  643.     if (typeof(IsFirstLink._linkTable) == 'undefined')
  644.     {
  645.       IsFirstLink._linkTable = new Array();
  646.       IsFirstLink._linkTable[sKey] = 1;
  647.       return true;
  648.     }
  649.  
  650.     if (!IsFirstLink._linkTable[sKey])
  651.     {
  652.       IsFirstLink._linkTable[sKey] = 1;
  653.       return true;
  654.     }
  655.  
  656.     return false;
  657.  
  658.   }
  659.  
  660.   // In the current document, is this node the first of its type (term)
  661.   // using this node's rid.
  662.   // JK: This is the origianl IsFirst definition.
  663.   // This is a temporary workaround until glossary becomes part of lookup.
  664.   function IsFirstTerm(o)
  665.   {
  666.     var oTestNode;
  667.     var sID = o.getAttribute("rid");
  668.     if (!sID) return false;
  669.     var oNestedVersions = o.ownerDocument.selectNodes("/inetsdk:topic/inetsdk:acronyms/acronym[./primary/tla/@rid = '" + sID + "']");
  670.     var oThisNode;
  671.     // find the first node in the document that uses this id.
  672.     var oNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + sID + "']");
  673.  
  674.     if (!oNode)
  675.     {
  676.       switch(o.parentNode.nodeName)
  677.       {
  678.         case "primary":
  679.         {
  680.           //need to check if there is another node that shares this tla...
  681.         if(oNestedVersions.length>0)
  682.         {
  683.           oThisNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + o.parentNode.parentNode.getAttribute("id") + "']");
  684.           if(oThisNode)
  685.           {
  686.               for(i=0;i<oNestedVersions.length;i++)
  687.               {
  688.                 oTestNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + oNestedVersions[i].getAttribute("id") + "']");
  689.                 if (oTestNode)
  690.                 {
  691.                   if (uniqueID(oTestNode) < uniqueID(oThisNode))
  692.                   {
  693.                     return false;
  694.                   }
  695.                 }
  696.               }
  697.  
  698.               return true;
  699.             }
  700.             else
  701.             {
  702.               return true;
  703.             }
  704.         }
  705.         else
  706.         {
  707.           return true;
  708.         }
  709.  
  710.         break;
  711.  
  712.         }
  713.         case "secondary":
  714.         {
  715.           return false;
  716.         break;
  717.         }
  718.         default:
  719.         {
  720.         }
  721.  
  722.       }
  723.     return true;
  724.     }
  725.   else
  726.     {
  727.     switch(o.parentNode.nodeName)
  728.     {
  729.       case "secondary":
  730.       {
  731.         return false;
  732.         break;
  733.       }
  734.       case "primary":
  735.       {
  736.         oThisNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + o.parentNode.parentNode.getAttribute("id") + "']");
  737.         if(oThisNode)
  738.         {
  739.           if (uniqueID(oNode) < uniqueID(oThisNode))
  740.           {
  741.             return false;
  742.           }
  743.  
  744.             if (oNestedVersions.length>0)
  745.             {
  746.               for(i=0;i<oNestedVersions.length;i++)
  747.               {
  748.                 oTestNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + oNestedVersions[i].getAttribute("id") + "']");
  749.                 if (oTestNode)
  750.                 {
  751.                   if (uniqueID(oTestNode) < uniqueID(oThisNode))
  752.                   {
  753.                     return false;
  754.                   }
  755.                 }
  756.               }
  757.  
  758.               return true;
  759.             }
  760.             else
  761.             {
  762.               return true;
  763.             }
  764.           }
  765.           else
  766.           {
  767.             return true;
  768.           }
  769.       }
  770.       default:
  771.       {
  772.         //this should be the case where there it isn't a nested tla...
  773.         break;
  774.       }
  775.     }
  776.   }
  777.  
  778.     if (uniqueID(oNode) == uniqueID(o))
  779.     {
  780.       if (oNestedVersions.length>0)
  781.       {
  782.         for(i=0;i<oNestedVersions.length;i++)
  783.         {
  784.           oTestNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + oNestedVersions[i].getAttribute("id") + "']");
  785.           if (oTestNode)
  786.           {
  787.             if (uniqueID(oTestNode) < uniqueID(oNode))
  788.             {
  789.               return false;
  790.             }
  791.           }
  792.         }
  793.  
  794.         return true;
  795.       }
  796.       else
  797.       {
  798.         return true;
  799.       }
  800.     }
  801.     else
  802.     {
  803.       if(o.parentNode.nodeName=="primary")
  804.       {
  805.         return true;
  806.       }
  807.       else
  808.       {
  809.         return false;
  810.       }
  811.     }
  812.   }
  813.  
  814.  
  815.   // Change the file extension of the path. If the extension is empty,
  816.   // do nothing
  817.   function ChangeExt(sPath, sExt)
  818.   {
  819.     if (!sExt || /^$/.test(sExt))
  820.     {
  821.       return sPath;
  822.     }
  823.  
  824.     if (!/^\./.test(sExt))
  825.     {
  826.       sExt = "." + sExt;
  827.     }
  828.  
  829.     return sPath.substring(0, sPath.lastIndexOf(".")) + sExt;
  830.   }
  831.  
  832.   // Given d:\foo\bar\goo.htm, return "htm"
  833.   function JustExt(sPath)
  834.   {
  835.     var iPos = sPath.lastIndexOf(".");
  836.     if (iPos >= 0 && sPath.length > iPos+1)
  837.     {
  838.       return sPath.substring(iPos+1);
  839.     }
  840.     else
  841.     {
  842.       return "";
  843.     }
  844.   }
  845.  
  846.   // Given d:\foo\bar\goo.htm, return "goo.htm"
  847.   function JustFName(sPath)
  848.   {
  849.     sPath =  sPath.replace(/[\\\\]/g, "/"); // convert backslashes to forward slashes
  850.     var aParts = sPath.split("/"); // split on forward slash
  851.     return aParts[aParts.length-1];
  852.   }
  853.  
  854.   // Given d:\foo\bar\goo.htm, return "d:\foo\bar"; slashes a reversed
  855.   function JustPath(sPath)
  856.   {
  857.     sPath =  sPath.replace(/[\\\\]/g, "/"); // convert backslashes to forward slashes
  858.     var aParts = sPath.split("/"); // split on forward slash
  859.     aParts.length -= 1;
  860.     return (aParts.length == 0 ? "." : aParts.join("/"));
  861.   }
  862.  
  863.   // Given d:\foo\bar\goo.htm, return "goo"
  864.   function JustStem(sPath)
  865.   {
  866.     var sFile = JustFName(sPath);
  867.     var aParts = sFile.split(".");
  868.     aParts.length -= 1;
  869.     return aParts.join(".");
  870.   }
  871.  
  872.  
  873.   // dependency: observe the explicit XQL query
  874.   function GetPublishedPathOfTopic()
  875.   {
  876.     if (typeof(GetPublishedPathOfTopic.pubpath) == 'string')
  877.     {
  878.       return GetPublishedPathOfTopic.pubpath;
  879.     }
  880.  
  881.     var oPubPath = ownerDocument.selectSingleNode("/HTML/HEAD/ph:header/ph:data/XML[@ID='_topicdata']/@pubpath");
  882.     if (oPubPath)
  883.     {
  884.       return (GetPublishedPathOfTopic.pubpath = oPubPath.value);
  885.     }
  886.     else
  887.     {
  888.       return null;
  889.     }
  890.   }
  891.  
  892.   // wraps the GeneratePath call because returning null to an xsl:eval is fatal
  893.   function GeneratePathWrapper(sPubPath, sDestPath, sMedia)
  894.   {
  895.     var sFinalPath = GeneratePath(sPubPath, sDestPath, sMedia);
  896.     if (typeof(sFinalPath) == 'string')
  897.     {
  898.       return sFinalPath;
  899.     }
  900.     else
  901.     {
  902.       return "";
  903.     }
  904.   }
  905.  
  906.   //  Build a path relative to the published location of the current
  907.   //  topic if the media is 'chm' or 'HXS'.
  908.   //  Otherwise return the path unchanged.
  909.   function GeneratePath(sPubPath, sDestPath, sMedia)
  910.   {
  911.     if (typeof(sMedia) != 'string' || (sMedia != 'chm' && sMedia != 'hxs' && sMedia != 'web'))
  912.     {
  913.       return sDestPath;
  914.     }
  915.  
  916.     if (!sPubPath)
  917.     {
  918.       // BUGBUG: Cache the error somewhere
  919.       //oDest.error = "published path unavailable";
  920.       return null;
  921.     }
  922.  
  923.     var sHREF;
  924.     // BUGBUG: htm extension is hard-coded in the CHM case.
  925.     sHREF = MakeRelative(sPubPath, sDestPath);
  926.     if (!sHREF)
  927.     {
  928.       // BUGBUG: Cache the error somewhere
  929.       //oDest.error = "VROOT2Relative failure.";
  930.       return null;
  931.     }
  932.     else
  933.     {
  934.       // extension map. Only change the target path if its extension is in the map.
  935.       // BUGBUG: Hardcoded...
  936.       var aExt = {'asp' : 'htm'};
  937.       var sExt = JustExt(sHREF);
  938.       if (sExt)
  939.       {
  940.         var sNewExt = aExt[sExt];
  941.         if (sNewExt)
  942.         {
  943.           sHREF = ChangeExt(sHREF, sNewExt);
  944.         }
  945.       }
  946.       return sHREF;
  947.     }
  948.  
  949.   }
  950.  
  951.   // Compose a path to the specified destination path relative to the specified container path
  952.   // The composition is performed case insensitively
  953.   function MakeRelative(sContainer, sDestPath)
  954.   {
  955.     // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  956.     //   /sitebuilder/shared/css/ie4-wks.css
  957.     //   ../../../../shared/css/ie4-wks.css
  958.  
  959.     // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  960.     //               /workshop/author/dhtml/reference/properties/accessKey.htm
  961.     //                                                properties/accessKey.htm
  962.  
  963.     // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  964.     //               /workshop/code/common.js
  965.     //               ../../../code/common.js
  966.  
  967.     // path is already relative
  968.     if (/^\.\./.test(sDestPath))
  969.     {
  970.       return sDestPath;
  971.     }
  972.  
  973.     // normalize the paths
  974.     var oRegBS = /\\/g;
  975.     sContainer = sContainer.replace(oRegBS, "/");
  976.     sDestPath = sDestPath.replace(oRegBS, "/");
  977.  
  978.     if (/^http:\/\//.test(sDestPath))
  979.     {
  980.       return sDestPath;
  981.     }
  982.  
  983.     // BUGBUG: make sure topics are on the same drive/protocol/server
  984.     var oRegNoProtocol = /^(file:\/\/\/)?([a-zA-z]):/;
  985.     sContainer = sContainer.replace(oRegNoProtocol, "");
  986.     sDestPath = sDestPath.replace(oRegNoProtocol, "");
  987.  
  988.     sDestPath = sDestPath.replace(/^\//, ""); // lop leading slash to eliminate empty first array element after split
  989.  
  990.     var aSrc = sContainer.split(/\//);
  991.     aSrc.length -= 1; // lop off the filename from the container (assume container is a reference to a file)
  992.  
  993.     var bTrailingSlash = (/\/$/.test(sDestPath)); // preserve trailing slash
  994.     var aDest = sDestPath.split(/\//);
  995.  
  996.     var iSrcLen = aSrc.length, iDestLen = aDest.length;
  997.     var iSrcIndex = 0, iDestIndex = 0, iNoMatch = 0;
  998.  
  999.     // walk forward looking for matching portion of path
  1000.     var bMatched = 0;
  1001.     for (iSrcIndex = 0; iSrcIndex < iSrcLen; iSrcIndex++)
  1002.     {
  1003.       if (aSrc[iSrcIndex].toLowerCase() != aDest[iDestIndex].toLowerCase())
  1004.       {
  1005.         iNoMatch++;
  1006.       }
  1007.       else
  1008.       {
  1009.         bMatched =  1;
  1010.         break;
  1011.       }
  1012.     }
  1013.  
  1014.     if (bMatched)
  1015.     {
  1016.  
  1017.       var aRelPath = new Array();
  1018.  
  1019.       while (iSrcIndex < iSrcLen && iDestIndex < iDestLen && aSrc[iSrcIndex].toLowerCase() == aDest[iDestIndex].toLowerCase())
  1020.       {
  1021.         iSrcIndex++; iDestIndex++;
  1022.       }
  1023.  
  1024.       // tack remaining portion of destination path onto the end of the result
  1025.       while (iDestIndex < iDestLen)
  1026.       {
  1027.         aRelPath[aRelPath.length] = aDest[iDestIndex];
  1028.         iDestIndex++;
  1029.       }
  1030.  
  1031.       var sRelPath = aRelPath.join('/');
  1032.  
  1033.       // climb out of what remains of the source (excluding the filename)
  1034.       while (iSrcIndex < iSrcLen)
  1035.       {
  1036.         sRelPath = "../" + sRelPath;
  1037.         iSrcIndex++;
  1038.       }
  1039.  
  1040.       return sRelPath + (bTrailingSlash ? "/" : "");
  1041.     }
  1042.     else // BUGBUG: no overlap, so just return what was passed in?
  1043.     {
  1044.       return sDestPath;
  1045.     }
  1046.   }
  1047.  
  1048.   // return the string s with the first letter capitalized
  1049.   function Proper(s)
  1050.   {
  1051.     return (/^(.)(.*)/.test(s) ? RegExp.$1.toUpperCase() + RegExp.$2 : s);
  1052.   }
  1053.  
  1054.   // return the proper string associated with the supplied page type
  1055.   function ProperPageType(s)
  1056.   {
  1057.     switch ( s )
  1058.   {
  1059.   case "attribute":
  1060.   case "behavior":
  1061.   case "collection":
  1062.   case "constants":
  1063.   case "event":
  1064.   case "function":
  1065.   case "method":
  1066.   case "object":
  1067.   case "property":
  1068.   case "rule":
  1069.     return Proper( s );
  1070.   case "dhcmdid":
  1071.     return "Command Identifier";
  1072.   case "dhfilter":
  1073.     return "Filter";
  1074.   case "dhfilter_method":
  1075.     return "Method";
  1076.   case "dhfilter_property":
  1077.     return "Property";
  1078.   case "enum":
  1079.     return "Enumerated Type";
  1080.   case "howto":
  1081.     return "Tutorial";
  1082.   case "iface":
  1083.     return "Interface";
  1084.   case "ovw":
  1085.     return "Overview";
  1086.   case "pseudo_element":
  1087.     return "Pseudo-element";
  1088.   case "struct":
  1089.     return "Structure";
  1090.     default:
  1091.     return "";
  1092.   }
  1093.   }
  1094.  
  1095.   // chains 5-04-01
  1096.   // Used by glossary_page.xsl and alphabetic_link.xsl
  1097.   // Checks a gloss_entry node or nodeSet to see if any nodes contain all the filters defined for a page
  1098.   function CheckFilters(aGlossaryNodeOrNodes, bIsNodeSet)
  1099.   {
  1100.     var aPageTechs = this.selectNodes("//inetsdk:topic/metadata/tech");
  1101.     var aTechStrings = new Array();
  1102.     for (i = 0; i < aPageTechs.length; i++)
  1103.     {
  1104.         aTechStrings[i] = aPageTechs[i].getAttribute("value");
  1105.     }
  1106.     
  1107.     if (bIsNodeSet == false)
  1108.     {
  1109.         // aGlossaryNodeOrNodes is a single node
  1110.         aNodeTechs = aGlossaryNodeOrNodes.selectNodes("tech");
  1111.         if (aNodeTechs.length == 0) return true; // default is to include
  1112.         iNumberFound = 0;
  1113.         
  1114.         for (j = 0; j < aNodeTechs.length; j++)
  1115.         {
  1116.             for (k = 0; k < aTechStrings.length; k++)
  1117.             {
  1118.                 if (aTechStrings[k] == aNodeTechs[j].getAttribute("value"))
  1119.                     iNumberFound++                    
  1120.             }
  1121.         }
  1122.         
  1123.         if (iNumberFound == aTechStrings.length) return true;
  1124.     }
  1125.     else
  1126.     {
  1127.         // for each node, check to see if all page techs are present
  1128.         // if so, set bFound to true  
  1129.         for (i = 0; i < aGlossaryNodeOrNodes.length; i++)
  1130.         {
  1131.             oNode = aGlossaryNodeOrNodes[i];
  1132.             aNodeTechs = oNode.selectNodes("tech");
  1133.             if (aNodeTechs.length == 0) return true; // default is to include
  1134.             iNumberFound = 0;
  1135.             
  1136.             for (j = 0; j < aNodeTechs.length; j++)
  1137.             {
  1138.                 for (k = 0; k < aTechStrings.length; k++)
  1139.                 {
  1140.                     if (aTechStrings[k] == aNodeTechs[j].getAttribute("value"))
  1141.                         iNumberFound++                    
  1142.                 }
  1143.             }
  1144.             
  1145.             if (iNumberFound == aTechStrings.length) return true;
  1146.         }
  1147.     }
  1148.     
  1149.     return false;
  1150.   }
  1151.  
  1152.   // chains 6-8-01
  1153.   // Used by utopia-wks.xsl
  1154.   // Creates string for @content in META @description
  1155.   // Converts quotes and apostrophies to entities
  1156.   // Removes line breaks and tabs.
  1157.   // This function is necessary for Utopia because the META description 
  1158.   // becomes a jscript object property in the utopia-wks.xsl transform
  1159.   // BUGBUG: currently loses text for xref and tla nodes in oNode 
  1160.   // It should apply a stylesheet to oNode that converts these nodes to text
  1161.   function FormatNodeForMETA(oNode, sXSL)
  1162.   {
  1163.     var sText = "";
  1164.     if (!oNode) return sText;
  1165.     sText = oNode.text;
  1166.  
  1167.     var i = 0;
  1168.     while ((i = sText.indexOf("\"")) != -1)
  1169.     {
  1170.         sText = sText.substring(0, i) + """ + sText.substring(i + 1);
  1171.     }
  1172.     
  1173.     //var i = 0;
  1174.     while ((i = sText.indexOf("\'")) != -1)
  1175.     {
  1176.         sText = sText.substring(0, i) + "'" + sText.substring(i + 1);
  1177.     }
  1178.  
  1179.     //var i = 0;
  1180.     while ((i = sText.indexOf("\n")) != -1)
  1181.     {
  1182.         sText = sText.substring(0, i) + sText.substring(i + 1);
  1183.     }
  1184.  
  1185.     //var i = 0;
  1186.     while ((i = sText.indexOf("\r")) != -1)
  1187.     {
  1188.         sText = sText.substring(0, i) + sText.substring(i + 1);
  1189.     }
  1190.  
  1191.     //var i = 0;
  1192.     while ((i = sText.indexOf("\t")) != -1)
  1193.     {
  1194.         sText = sText.substring(0, i) + sText.substring(i + 1);
  1195.     }
  1196.  
  1197.     return sText;
  1198.   }
  1199.   
  1200. // chains 6-19-01
  1201. // Used by scr_property.xsl
  1202. // Helps page determine whether property belongs to an HTML element 
  1203. // and should use a syntax section that includes HTML syntax
  1204. function DoesObjectHavePN()
  1205. {
  1206.     var oObjectNodes;
  1207.     var oTNode;
  1208.     var sRid = "";
  1209.     var sPN = "";
  1210.  
  1211.     oObjectNodes = this.selectNodes("//metadata/applies/object");
  1212.     
  1213.     for (i = 0; i < oObjectNodes.length; i++)
  1214.     {
  1215.         sRid = oObjectNodes(i).getAttribute("rid");
  1216.         oTNode = goLookup.RetrieveTarget(sRid);
  1217.         if (!oTNode) continue;
  1218.         else sPN = oTNode.getAttribute("pn")
  1219.         if (sPN && sPN != "") return true;
  1220.     }
  1221.     
  1222.     return false;
  1223. }
  1224.  
  1225. // chains 6-20-01
  1226. // Used by scr_property.xsl
  1227. // Helps page determine whether property belongs to an HTML element 
  1228. // and should use a syntax section that includes HTML syntax
  1229. function ObjectTypeEquals(sType)
  1230. {
  1231.     var oObjectNodes;
  1232.     var oTNode;
  1233.     var sRid = "";
  1234.     var sObjectType = "";
  1235.  
  1236.     oObjectNodes = this.selectNodes("//metadata/applies/object");
  1237.     
  1238.     for (i = 0; i < oObjectNodes.length; i++)
  1239.     {
  1240.         sRid = oObjectNodes(i).getAttribute("rid");
  1241.         oTNode = goLookup.RetrieveTarget(sRid);
  1242.         if (!oTNode) continue;
  1243.         else sObjectType = oTNode.getAttribute("type")
  1244.         if (sObjectType && sObjectType == sType) return true;
  1245.     }
  1246.     
  1247.     return false;
  1248. }
  1249.  
  1250. // chains 6-26-01: Used by utopia-wks.xsl
  1251. // Script inserted into Utopia template via sHeaderString must have additional back slashes in
  1252. // line breaks and quotes for proper escape character sequence
  1253. function FormatForUtopiaHeaderString(oNode, sProjRoot)
  1254. {
  1255.     var sText = "";
  1256.     if (!oNode) return sText;
  1257.  
  1258.     var sTestString = "/production/xml/";
  1259.     var sReplacementText = sProjRoot + "/";
  1260.     var oRegExp = new RegExp(sTestString, "g");
  1261.  
  1262.     sText = oNode.xml;
  1263.  
  1264.     if (sText.indexOf(sTestString) != -1) 
  1265.         sText = sText.replace(oRegExp, sReplacementText);
  1266.  
  1267.     var i = 0;
  1268.     while ((i = sText.indexOf("\n", i)) != -1)
  1269.     {
  1270.         sText = sText.substring(0, i - 1) + "\\n" + sText.substring(i + 1);
  1271.     }
  1272.  
  1273.     var i = 0;
  1274.     while ((i = sText.indexOf("\"", i + 2)) != -1)
  1275.     {
  1276.         sText = sText.substring(0, i) + "\\\"" + sText.substring(i + 1);
  1277.     }
  1278.  
  1279.     return sText;
  1280. }
  1281.  
  1282. // chains 6-26-01
  1283. // Used by utopia-wks.xsl
  1284. // Gets the name of a file from an @HREF attribute that specifies a path to a script or css file
  1285. function GetFileName(oNode)
  1286. {
  1287.     var sFileName = "";
  1288.     if (!oNode) return sFileName;
  1289.     
  1290.     sFullName = oNode.nodeValue;
  1291.     if (sFullName == "") return sFileName;
  1292.  
  1293.     var iLastSlash = sFullName.lastIndexOf("/");
  1294.     if (iLastSlash == -1) iLastSlash = sFullName.lastIndexOf("\\");
  1295.     if (iLastSlash == -1) return sFileName;
  1296.     else return sFullName.substring(iLastSlash + 1);
  1297. }
  1298.  
  1299. function  BuildObjectList()
  1300. {
  1301. //debugger;
  1302.     var sRet = "";
  1303.     var oXMLDoc = this.ownerDocument;
  1304.     var sName = oXMLDoc.selectSingleNode("//metadata/@name").value;
  1305.     var sCriteria = "[dlang/@value='" + goLookup._oCtx._devlang + "']";
  1306.     //if (!NeedsDisambiguation(sName, goDest, sCriteria))
  1307.     //    return sRet;
  1308.     // Check with lookupbyName type thing for multiple pages with same metadata/@name
  1309.     
  1310.     // construct string from applies/object (or applies/iface too?)
  1311.     var oAppliesNode = oXMLDoc.selectSingleNode("//applies");
  1312.     if (!oAppliesNode) return sRet;
  1313.     var oObjectNodes = oAppliesNode.selectNodes("object");
  1314.     sRet = " (";
  1315.     for (i = 0; (i < 3) && i < (oObjectNodes.length); i++)
  1316.     {
  1317.         sObjectRid = oObjectNodes[i].getAttribute("rid");
  1318.         // lookup in targets and get name
  1319.         goLookup.LookupByRID(sObjectRid, goDest);
  1320.         sObjectName = goDest.GetPersistentName();
  1321.         if (sObjectName == "" || sObjectName == undefined) sObjectName = goDest.GetCaption();
  1322.         //if (sObjectName == "") sObjectName = oObjTarg.GetAttribute("name");
  1323.         
  1324.         sRet = sRet + sObjectName;
  1325.         if (i + 1 < oObjectNodes.length && i < 2) sRet = sRet + ", ";
  1326.     }
  1327.     if (oObjectNodes.length > 3) sRet = sRet + ", ...";
  1328.     sRet = sRet + ")";
  1329.     return sRet;
  1330. }
  1331.  
  1332. /*
  1333. function NeedsDisambiguation(sName, oDest, sCriteria)
  1334. {
  1335.   var bRet = false;
  1336.   
  1337.   
  1338.   var bOk = false;
  1339.   var sTargXML = null;
  1340.   var sTPath = goLookup._oCtx._sDrive + goLookup._oCtx.GetPathOf("targets");
  1341.   var oTNodes = null;
  1342.   var oTNode = null;
  1343.   var oData = null;
  1344.   var bLuCache = goLookup._oCtx.CacheLookups();
  1345.  
  1346.   oData = goLookup.EnsureData(bLuCache);
  1347.   bLuCache = goLookup._oCtx.CacheLookups();
  1348.  
  1349.   oDest.Init();
  1350.  
  1351.   if (sName)
  1352.   {
  1353.     oDest.SetCaption(sName);
  1354.  
  1355.     sCriteria = NormalizeCriteria(sCriteria);
  1356.  
  1357.     if (bLuCache && oData)
  1358.     {
  1359.       // Try to use the LuCache Lookup Cache.
  1360.       try
  1361.       {
  1362.         // Call LuCache to lookup the name and get back the node-xml.
  1363.         sTargXML = oData.LookupField(sName, "name", sTPath, sCriteria);
  1364.       }
  1365.       catch(e)
  1366.       {
  1367.         sTargXML = null;
  1368.       }
  1369.       if (sTargXML)
  1370.       {
  1371.         var oTDom = goLookup._oCtx._oTDom;
  1372.  
  1373.         // Now use mini-dom node to load node-xml and get a node.
  1374.         oTDom.async = false;
  1375.         oTDom.loadXML(sTargXML);
  1376.         oTNode = oTDom.documentElement;
  1377.         if (oTNode)
  1378.           bOk = true;
  1379.         else
  1380.           goLookup._error = "cannot load node xml.";
  1381.       }
  1382.       else
  1383.         goLookup._error = "cannot locate " + sName;
  1384.     }
  1385.     else
  1386.     {
  1387.       // Try to use a loaded DOM for lookups.
  1388.       if (bLuCache && !oData)
  1389.         oData = goLookup.EnsureData(false);
  1390.       if (oData)
  1391.       {
  1392.         oTNodes = oData.selectNodes("/inetsdk:targets/targ[@name='" + sName + "']" + sCriteria);
  1393.         //oTNodes = oTNodes.selectNodes("dlang[@value='" + sCriteria + "']");
  1394.         if (oTNodes.length > 1) bRet = true;
  1395.       }
  1396.       else
  1397.         goLookup._error = "cannot create access to targets.";
  1398.     }
  1399.   }
  1400.  
  1401.   return bRet;
  1402. }
  1403. */
  1404.  
  1405. function NeedsNewGif()
  1406. {
  1407.     //return true;
  1408.     sXml = this.xml;
  1409.     if (sXml.indexOf("new.gif") != -1) return true;
  1410.     else return false;
  1411. }
  1412.  
  1413.   /********************
  1414.   * unused code below *
  1415.   *********************/
  1416.  
  1417.   // force see also links to be enabled
  1418.   //BUGBUG: Can't modify a read-only node.
  1419.   //BUGBUG: By design the XML document is read-only during transformation.
  1420.   /*
  1421.   function TweakXrefs(o)
  1422.   {
  1423.     var aPaths = new Array("inetsdk:topic/content/seealso/xref");
  1424.     for (var i = 0; i < aPaths.length; i++)
  1425.     {
  1426.       var oSeeNodes = o.selectNodes(aPaths[i]);
  1427.       for (var i = 0; i < oSeeNodes.length; i++)
  1428.       {
  1429.         var oNode = oSeeNodes(i);
  1430.         oNode.setAttribute("enabled", "1");
  1431.       }
  1432.     }
  1433.   }
  1434.  
  1435.   function IsHex(s)
  1436.   {
  1437.     return s.match(/^0x/i) ? true : false;
  1438.   }
  1439.  
  1440.   // convert s to hexidecimal
  1441.   function toHex(s)
  1442.   {
  1443.     var sHexDigits = "0123456789ABCDEF", sResult = "";
  1444.  
  1445.     s = parseInt(s);
  1446.  
  1447.     while (s > 15)
  1448.     {
  1449.       i = s % 16;
  1450.       sResult = sHexDigits.charAt(i) + sResult;
  1451.       s = Math.floor(s/16);
  1452.     }
  1453.     sResult = sHexDigits.charAt(s) + sResult;
  1454.     return sResult;
  1455.   }
  1456.  
  1457.  
  1458.   // VB outputs values in decimal format.
  1459.   // In the lower pane of the object browser it outputs values >= 16 in decimal followed by (&Hxx)
  1460.   function VBOutput(s)
  1461.   {
  1462.     var iResult = parseInt(s);
  1463.     var sResult = "";
  1464.     sResult += iResult;
  1465.  
  1466.     // append the hex value if s is big enough
  1467.     if (iResult >= 16)
  1468.     {
  1469.       sResult += " '";
  1470.       if (IsHex(s))
  1471.       {
  1472.         sResult += s.replace(/^0x/i, '&H');
  1473.       }
  1474.       else
  1475.       {
  1476.         sResult += "&H" + toHex(iResult);
  1477.       }
  1478.     }
  1479.  
  1480.     return sResult;
  1481.   }
  1482.  
  1483.   Not currently in use
  1484.   // Strip the protocol from the beginning of the specified path.
  1485.   function StripProtocol(s)
  1486.   {
  1487.     return s.replace(/^((file|http):)?\/+([a-z]:)?/i, "")
  1488.   }
  1489.  
  1490.   // formerly used to handle building the VARIANT subtype string when resolving a dtype
  1491.   // Now we use pure script instead
  1492.   function IsSecond2Last(o)
  1493.   {
  1494.     var iSiblings = o.parentNode.childNodes.length;
  1495.     return (childNumber(o) == iSiblings-1) ? true : false;
  1496.   }
  1497.  
  1498.   */
  1499. ]]>
  1500.